﻿using System;

namespace BabyNames
{
    //
    // This class represents a single baby name, including ranking info for 1900..2000.
    // The data was collected by the United States Social Security Administration.  For 
    // more info, see: http://www.ssa.gov/OACT/babynames/.
    //
    // Prof Joe Hummel
    // June 2006
    // 
    public class BabyName : IComparable 
    {
        //
        // Data fields: name, and ranks for 1900..2000.
        //
        private readonly string _mName;
        private readonly int[] _mRanks;  // 11 ranks: 1900, 1910, ..., 2000

        //
        // Properties
        //
        public string Name
        {
            get { return _mName; }
        }

        //
        // Constructor: initializes baby name object based on a rank string, which contains
        //   12 values: the name, followed by 11 rankings (1900, 1910, ..., 2000).
        //
        public BabyName(string nameAndRankings)
        {
            char[] separators = { ' ' };

            // break line into 12 tokens: name and 11 rankings:
            string[] tokens = nameAndRankings.Split(separators, StringSplitOptions.RemoveEmptyEntries);
            _mName = tokens[0];
            _mRanks = new int[11];
            for (int i = 0; i < 11; i++)
                _mRanks[i] = int.Parse(tokens[i + 1]);
        }

        //
        // Returns the rank of this name for the given year 1900, 1910, 1920, ..., 2000.
        //
        public int Rank(int year)
        {
            int index = (year - 1900) / 10;
            if (index < 0 || index > 10)
                throw new ArgumentException("Invalid year, must be 1900, 1910, ..., 2000");

            return _mRanks[index];
        }

        //
        // Returns the average ranking across the century for this name.
        //
        public int AverageRank()
        {
            //
            // NOTE: a rank of 0 doesn't rank in the popularity, so we treat that as a
            // ranking of 2500 to generate a more accurate average.
            //
            int sum = 0;
            foreach (int t in _mRanks)
            {
                if (t == 0)
                    sum = sum + 2500;
                else
                    sum = sum + t;
            }

            return sum / _mRanks.Length;
        }

        //
        // Returns the trend (i.e. average change) over the last 20 years (1980..2000)
        //   of the century for this  name; this is a positive value if the name is
        //   becoming more popular, a negative value if the name is becoming less popular,
        //   and zero if the name didn't change in popularity or the change isn't
        //   consistent (increase then decrease, or vice versa).
        //
        public int Trend()
        {
            //
            // NOTE: a rank of 0 doesn't rank in the popularity, so we treat that as a
            // ranking of 2500 to generate a more accurate average.
            //
            int r1980 = (_mRanks[8] == 0) ? 2500 : _mRanks[8];
            int r1990 = (_mRanks[9] == 0) ? 2500 : _mRanks[9];
            int r2000 = (_mRanks[10] == 0) ? 2500 : _mRanks[10];

            //
            // Note that the HIGHER the ranking, the LESS popular the name; e.g. 1 is the 
            // most popular name that decade.
            //
            int diff80S = r1980 - r1990;
            int diff90S = r1990 - r2000;

            if (diff80S < 0 && diff90S > 0)  // inconsistent
                return 0;
            if (diff80S > 0 && diff90S < 0)  // inconsistent
                return 0;
            return (diff80S + diff90S) / 2;
        }
        
        public int CompareTo(object obj)
        {
            if (obj == null) return 1;

            var other = obj as BabyName;
            if (other != null)
                return Name.CompareTo(other.Name);
            else
                throw new ArgumentException("Object is not a BabyName");
        }
    }//class

}